import { LeftOutlined, RightOutlined } from '@ant-design/icons';
import { List, Card, message } from 'antd';
import { useEffect, useMemo, useRef, useState } from 'react';

import knowService from '@/api/services/knowService';
import { Button } from '@/components/eai-design';
import { SvgIcon } from '@/components/icon';
import Markdown from '@/components/markdown';
import NotData from '@/components/NotData';
import { useKnowledgeStore } from '@/store/knowledge';
import { AutoCorrectListType, AutoCorrectTrunksType, OptimizedistType } from '@/types/know/know';

interface DocumentProcessingWronglyModalsProps {
  collectionItem: OptimizedistType;
  flag?: boolean;
}

const DocumentProcessingWronglyModals = ({
  collectionItem,
  flag,
}: DocumentProcessingWronglyModalsProps) => {
  const [wronglyList, setWronglyList] = useState<AutoCorrectListType[]>([]);
  const [trunksList, setTrunksList] = useState<AutoCorrectTrunksType[]>();
  const [activeIndex, setActiveIndex] = useState(0);
  const [activeWord, setActiveWord] = useState('');
  const [activeOccurrence, setActiveOccurrence] = useState(0);
  const previewRef = useRef<HTMLDivElement>(null);
  const { setListLength } = useKnowledgeStore();

  useEffect(() => {
    getAutoCorrectList();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [collectionItem]);

  useEffect(() => {
    if (flag !== undefined) {
      changeAllIgnore();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [flag]);

  useEffect(() => {
    if (wronglyList && wronglyList.length > 0) {
      const first = wronglyList[0];
      setActiveIndex(0);
      setActiveWord(first.correctedText);
      setActiveOccurrence(0);

      setTimeout(() => {
        const container = previewRef.current;
        if (!container) return;
        const el = container.querySelector('#selected-highlight') as HTMLElement | null;
        if (el) {
          el.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'nearest' });
        }
      }, 100);
    }
    setListLength(wronglyList?.length || 0);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [wronglyList]);

  const getAutoCorrectList = async () => {
    try {
      const res = await knowService.autoCorrectList(
        collectionItem.collectionId,
        collectionItem.appId,
      );
      setWronglyList(res.auto_correct_pairs_with_count);
      setTrunksList(res.trunks);
    } catch (error) {
      console.log(error);
    }
  };

  const escapeReg = (s: string) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');

  const displayTrunks = useMemo(() => {
    if (!trunksList || trunksList.length === 0) return [] as any[];
    const sorted = [...trunksList].sort((a, b) => (a.chunkIndex || 0) - (b.chunkIndex || 0));
    const result: any[] = [];
    for (let i = 0; i < sorted.length; i += 1) {
      const current = sorted[i];
      result.push(current);
      const next = sorted[i + 1];
      if (next && (next.chunkIndex || 0) !== (current.chunkIndex || 0) + 1) {
        result.push({ _id: `omitted-${current._id}-${i}`, omitted: true });
      }
    }
    return result;
  }, [trunksList]);

  useEffect(() => {
    const container = previewRef.current;
    if (!container) return;
    const timer = setTimeout(() => {
      const el = container.querySelector('#selected-highlight') as HTMLElement | null;
      if (el) {
        el.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'nearest' });
      }
    }, 0);
    // eslint-disable-next-line consistent-return
    return () => clearTimeout(timer);
  }, [activeOccurrence, activeWord, trunksList]);

  function highlightTypos(text: string, chunkId?: string) {
    if (!wronglyList || wronglyList.length === 0 || !chunkId) return text;

    const current = wronglyList[activeIndex];
    const activeIds = current?.chunkIdList || [];
    const activeTargetId =
      activeIds[Math.min(Math.max(activeOccurrence, 0), Math.max(activeIds.length - 1, 0))];

    const redWrap = (s: string) =>
      `<span id="selected-highlight" style="background:#FFF1EE;color:#f5222d;font-weight:600;border-bottom:2px solid #FC5353;">${s}</span>`;
    const yellowWrap = (s: string) =>
      `<span style="background:#FFFECA;font-weight:600;border-bottom:2px solid #FFED7B;">${s}</span>`;

    type Range = { start: number; end: number; wrap: (s: string) => string };
    const ranges: Range[] = [];

    wronglyList.forEach((item, idx) => {
      if (
        typeof item?.originalIndices !== 'number' ||
        !item?.correctedText ||
        !(item?.chunkIdList || []).includes(chunkId)
      )
        return;
      const pos = item.originalIndices as number;
      const word = item.correctedText as string;
      const normalizeWidth = (s: string) =>
        Array.from(s)
          .map((ch) => {
            const cp = ch.codePointAt(0) as number;
            if (cp === 0x3000) return ' ';
            if (cp >= 0xff01 && cp <= 0xff5e) return String.fromCodePoint(cp - 0xfee0);
            return ch;
          })
          .join('');
      const segment = text.slice(pos, pos + word.length);
      if (
        pos >= 0 &&
        pos + word.length <= text.length &&
        normalizeWidth(segment) === normalizeWidth(word)
      ) {
        const wrap = idx === activeIndex && chunkId === activeTargetId ? redWrap : yellowWrap;
        ranges.push({ start: pos, end: pos + word.length, wrap });
      }
    });

    if (ranges.length === 0) return text;
    ranges.sort((a, b) => a.start - b.start);
    const nonOverlapping: Range[] = [];
    let lastEnd = -1;
    ranges.forEach((r) => {
      if (r.start >= lastEnd) {
        nonOverlapping.push(r);
        lastEnd = r.end;
      }
    });

    let out = '';
    let cursor = 0;
    nonOverlapping.forEach((r) => {
      out += text.slice(cursor, r.start);
      out += r.wrap(text.slice(r.start, r.end));
      cursor = r.end;
    });
    out += text.slice(cursor);
    return out;
  }

  const changeIgnore = (item: AutoCorrectListType) => {
    if (!item?.correctedText) return;
    try {
      knowService.ignoreAutoCorrect({
        collectionId: collectionItem.collectionId,
        appId: collectionItem.appId,
        type: 'correct',
        word: [item.correctedText],
        optimizeText: [item.originalText],
        status: 0,
        originalIndices: [item.originalIndices],
      });
      setWronglyList((prev) => prev?.filter((w) => w.correctedText !== item.correctedText));
    } catch (error) {
      message.error('忽略失败');
    }
  };

  const changeAllIgnore = () => {
    const typoList = wronglyList || [];
    try {
      knowService.ignoreAutoCorrect({
        collectionId: collectionItem.collectionId,
        appId: collectionItem.appId,
        type: 'correct',
        word: typoList.map((item) => item.correctedText),
        optimizeText: typoList.map((item) => item.originalText),
        status: 1,
        originalIndices: typoList.map((item) => item.originalIndices),
      });
      setWronglyList([]);
    } catch (error) {
      message.error('忽略失败');
    }
  };

  const changeReplace = (item: AutoCorrectListType) => {
    if (!item?.correctedText || !item?.originalText) return;
    const targetChunkIds = item.chunkIdList || [];
    const normalizeWidth = (s: string) =>
      Array.from(s)
        .map((ch) => {
          const cp = ch.codePointAt(0) as number;
          if (cp === 0x3000) return ' ';
          if (cp >= 0xff01 && cp <= 0xff5e) return String.fromCodePoint(cp - 0xfee0);
          return ch;
        })
        .join('');

    setTrunksList((prev) => {
      if (!prev) return prev;
      return prev.map((chunk) => {
        if (!targetChunkIds.includes(chunk._id)) return chunk;
        const pos = typeof item.originalIndices === 'number' ? item.originalIndices : -1;
        if (pos < 0) return chunk;
        const from = item.correctedText as string;
        const to = item.originalText as string;
        const seg = chunk.text.slice(pos, pos + from.length);
        if (normalizeWidth(seg) !== normalizeWidth(from)) return chunk;
        const newText = chunk.text.slice(0, pos) + to + chunk.text.slice(pos + from.length);
        return { ...chunk, text: newText } as AutoCorrectTrunksType;
      });
    });
    try {
      knowService.updateOptimize({
        collectionId: collectionItem.collectionId,
        appId: collectionItem.appId,
        type: 'correct',
        word: [item.correctedText],
        optimizeText: [item.originalText],
        status: 0,
        originalIndices: [item.originalIndices],
      });
      setWronglyList((prev) => prev?.filter((w) => w.correctedText !== item.correctedText));
    } catch (error) {
      message.error('替换失败');
    }
  };

  const replacement = () => {
    const typoList = wronglyList || [];
    const normalizeWidth = (s: string) =>
      Array.from(s)
        .map((ch) => {
          const cp = ch.codePointAt(0) as number;
          if (cp === 0x3000) return ' ';
          if (cp >= 0xff01 && cp <= 0xff5e) return String.fromCodePoint(cp - 0xfee0);
          return ch;
        })
        .join('');

    setTrunksList((prev) => {
      if (!prev) return prev;
      return prev.map((chunk) => {
        type Range = { start: number; end: number; replacement: string };
        const ranges: Range[] = [];

        typoList.forEach((item) => {
          if (!item?.correctedText || !item?.originalText) return;
          if (!Array.isArray(item?.chunkIdList) || !item.chunkIdList.includes(chunk._id)) return;
          const pos = typeof item.originalIndices === 'number' ? item.originalIndices : -1;
          if (pos < 0) return;
          const from = item.correctedText as string;
          const to = item.originalText as string;
          const seg = chunk.text.slice(pos, pos + from.length);
          if (normalizeWidth(seg) === normalizeWidth(from)) {
            ranges.push({ start: pos, end: pos + from.length, replacement: to });
          }
        });

        if (ranges.length === 0) return chunk;

        ranges.sort((a, b) => a.start - b.start);
        const nonOverlapping: Range[] = [];
        let lastEnd = -1;
        ranges.forEach((r) => {
          if (r.start >= lastEnd) {
            nonOverlapping.push(r);
            lastEnd = r.end;
          }
        });

        let out = '';
        let cursor = 0;
        nonOverlapping.forEach((r) => {
          out += chunk.text.slice(cursor, r.start);
          out += r.replacement;
          cursor = r.end;
        });
        out += chunk.text.slice(cursor);
        return { ...chunk, text: out } as AutoCorrectTrunksType;
      });
    });

    try {
      knowService.updateOptimize({
        collectionId: collectionItem.collectionId,
        appId: collectionItem.appId,
        type: 'correct',
        word: typoList.map((item) => item.correctedText),
        optimizeText: typoList.map((item) => item.originalText),
        status: 1,
        originalIndices: typoList.map((item) => item.originalIndices),
      });
      setWronglyList([]);
    } catch (error) {
      message.error('替换失败');
    }
  };

  const handleSelectCard = (item: AutoCorrectListType, index: number) => {
    setActiveIndex(index);
    setActiveWord(item.correctedText);
    setActiveOccurrence(0);

    setTimeout(() => {
      const container = previewRef.current;
      if (!container) return;
      const el = container.querySelector('#selected-highlight') as HTMLElement | null;
      if (el) {
        const containerRect = container.getBoundingClientRect();
        const elementRect = el.getBoundingClientRect();
        const scrollAdjustment = elementRect.top - containerRect.top - containerRect.height / 2;
        container.scrollBy({ top: scrollAdjustment, behavior: 'smooth' });
      }
    }, 100);
  };

  const handlePrev = (total: number) => {
    if (total <= 1) return;
    setActiveOccurrence((prev) => Math.max(prev - 1, 0));
  };

  const handleNext = (total: number) => {
    if (total <= 1) return;
    setActiveOccurrence((prev) => Math.min(prev + 1, total - 1));
  };

  return (
    <div className="flex h-[600px]">
      {/* 左侧文档预览  */}
      <div className="mr-4 flex w-[50%] flex-1 flex-col rounded-xl bg-bg-3">
        <div className="h-full overflow-auto rounded-md  p-4">
          <div className="mb-4 flex items-center">
            <SvgIcon size={32} icon="document-ic1" className="mr-2" />
            <div className="min-w-0 flex-1 text-@brand-color">
              <div className="truncate text-base font-semibold text-text-5">
                {collectionItem.fileName}
              </div>
              <div className="mt-1 text-xs text-text-3">
                {collectionItem.size} · {collectionItem.passTime}
              </div>
            </div>
          </div>
          <div
            ref={previewRef}
            className="hide-scrollbar h-[85%] flex-1 overflow-auto text-xs leading-6 text-gray-700"
          >
            {displayTrunks.map((chunk: any) => {
              if (chunk.omitted) {
                return (
                  <div key={chunk._id} className="my-6">
                    <div className="flex items-center text-text-2">
                      <div className="flex-1 border-t border-dashed border-line-2" />
                      <div className="mx-4 text-sm">此段省略</div>
                      <div className="flex-1 border-t border-dashed border-line-2" />
                    </div>
                  </div>
                );
              }

              return (
                <div key={chunk._id} className="mb-6">
                  <Markdown source={highlightTypos(chunk.text, chunk._id)} />
                </div>
              );
            })}
          </div>
        </div>
      </div>

      {/* 右侧错别字列表  */}
      <div className="flex w-[40%] flex-col rounded-xl bg-bg-3 p-4">
        <div className="text-sm font-semibold text-text-5">错别字列表</div>
        <div className="mb-4 ">
          <div className="flex items-center justify-between">
            <div className="text-xs text-text-5">
              识别到
              <span className="font-semibold">{wronglyList?.length}</span>
              项错别字问题
            </div>
            {wronglyList?.length > 0 && (
              <div className="flex gap-2">
                <Button
                  className="rounded-default bg-@brand-color px-4 py-1 text-white"
                  onClick={changeAllIgnore}
                >
                  忽略该问题
                </Button>
                <Button
                  className="rounded-default !bg-[#1E6FFA] px-4 py-1 !text-white "
                  onClick={replacement}
                  type="default"
                >
                  一键替换
                </Button>
              </div>
            )}
          </div>
        </div>
        <div className="hide-scrollbar flex-1 overflow-auto">
          <List
            dataSource={wronglyList}
            locale={{ emptyText: <NotData /> }}
            renderItem={(item, index) => {
              const sel = index === activeIndex;
              const total = item?.count || 0;
              return (
                <Card
                  size="small"
                  className={`!mb-4 border ${sel ? '!border-@brand-color' : '!border-line-2'}`}
                  onClick={() => handleSelectCard(item, index)}
                >
                  <div className="mb-2 flex items-center">
                    <SvgIcon size={16} icon="document-ic2" className="mr-2" />

                    <span>
                      错别字 &quot;{item.correctedText}&quot; 建议替换为 &quot;{item.originalText}
                      &quot;
                    </span>
                  </div>
                  <div className={`flex items-center  ${sel ? 'justify-between' : ' justify-end'}`}>
                    {sel && (
                      <div className="flex gap-2">
                        <Button
                          size="small"
                          type="default"
                          className={`!border !border-line-2 !bg-fill-1 ${
                            total <= 1 || activeOccurrence === 0 ? '!text-text-2' : ''
                          }`}
                          disabled={total <= 1 || activeOccurrence === 0}
                          onClick={(e) => {
                            e.stopPropagation();
                            handlePrev(total);
                          }}
                        >
                          <LeftOutlined />
                        </Button>
                        <div className="flex items-center">
                          <span className="text-text-3">
                            {activeOccurrence + 1}/{total}
                          </span>
                        </div>
                        <Button
                          size="small"
                          type="default"
                          className={`!border !border-line-2 !bg-fill-1 ${
                            total <= 1 || activeOccurrence >= total - 1 ? '!text-text-2' : ''
                          }`}
                          disabled={total <= 1 || activeOccurrence >= total - 1}
                          onClick={(e) => {
                            e.stopPropagation();
                            handleNext(total);
                          }}
                        >
                          <RightOutlined />
                        </Button>
                      </div>
                    )}
                    <div className="flex gap-2">
                      <Button
                        size="small"
                        type="default"
                        className="!border !border-line-2 !bg-fill-1"
                        onClick={(e) => {
                          e.stopPropagation();
                          changeIgnore(item);
                        }}
                      >
                        忽略
                      </Button>
                      <Button
                        className="!border !border-@brand-color !text-@brand-color"
                        size="small"
                        type="default"
                        onClick={(e) => {
                          e.stopPropagation();
                          changeReplace(item);
                        }}
                      >
                        替换
                      </Button>
                    </div>
                  </div>
                </Card>
              );
            }}
          />
        </div>
      </div>
    </div>
  );
};

export default DocumentProcessingWronglyModals;
